#include "MyTree.h"
#include "checker.h"

int MyTree::_maxDepth = 1;
int MyTree::n = 0;
unsigned int MyTree::CountTrees = 0;
Move MyTree::Backup = Move(-1, -1);

bool MyTree::res_stat = false;

MyTree::MyTree() :  _currentDepth(0), heuristic(0), _lastMove(0, 0)
	, _addThisPointIfNoPoints(Move(-1, -1))
{
#ifdef _DEBUG
	Checker::Instance().addNew(this);
#endif
	MyTree::CountTrees++;
	this->board = new Board(Gomoku::Instance().Board);
	this->InitPoints();
}

MyTree::MyTree(Board* motherBoard, unsigned short x, unsigned short y, int depth) :  _currentDepth(depth + 1), _lastMove(x, y), heuristic(0)
	, _addThisPointIfNoPoints(Move(-1, -1))
{
#ifdef _DEBUG
	Checker::Instance().addNew(this);
#endif
	MyTree::CountTrees++;
	this->board = new Board(*motherBoard);
	this->SetValue(x, y);
}

MyTree::~MyTree()
{
	std::list<MyTree*>::iterator it = _Children.begin();
	for (; it != _Children.end(); ++it)
	{
		if ((*it) != NULL)
			delete *it;
	}
	_Children.clear();
	this->_Points.clear();
	delete board;
	MyTree::CountTrees--;
#ifdef _DEBUG
	Checker::Instance().addDelete(this);
#endif
}


void		MyTree::AddPiece()
{
	std::list<Move>::iterator it;
	std::list<Move>::iterator it_end = this->_Points.end();
	unsigned short x;
	unsigned short y;
	if (this->_Points.empty() && _addThisPointIfNoPoints._x != -1)
		this->_Points.push_back(_addThisPointIfNoPoints);

	for (it = this->_Points.begin(); it != it_end; ++it)
	{
		it->GetCoordinates(x, y);
		// -
		this->AddChild(x, y - 1);
		this->AddChild(x - 1, y); 
		this->AddChild(x - 1, y - 1);

		// +
		this->AddChild(x, y + 1);
		this->AddChild(x + 1, y);
		this->AddChild(x + 1, y + 1);

		// + et -
		this->AddChild(x - 1, y + 1);
		this->AddChild(x + 1, y - 1);
	}
	
	if (this->_currentDepth < _maxDepth)
	{
		std::list<MyTree*>::iterator it;
		std::list<MyTree*>::iterator it_end = this->_Children.end();

		for (it = this->_Children.begin(); it != it_end; ++it)
			(*it)->AddPiece();
	}
}

Move		MyTree::LaunchMinMax()
{
	if (this->_Children.size() != 0)
	{
		std::list<MyTree*>::iterator it = this->_Children.begin();
		std::list<MyTree*>::iterator it_end = this->_Children.end();
		--it_end;
		int max = std::numeric_limits<int>::min();
		int min = std::numeric_limits<int>::max();
		int	alpha = std::numeric_limits<int>::min();
		int beta = std::numeric_limits<int>::max();
		Move moveMax, moveMin;

		while (it_end != it)
		{
			if ((*it_end)->heuristic > max)
			{
				max = (*it_end)->heuristic;
				moveMax = (*it_end)->_lastMove;			
				//max = (*it_end)->heuristic;
				//moveMax = (*it_end)->_lastMove;
				//if(alpha > min) alpha = min;
				//if(beta <= alpha) { min = alpha; continue; }
			}
			if ((*it_end)->heuristic < min)
			{
				min = (*it_end)->heuristic;
				moveMin = (*it_end)->_lastMove;
				//min = (*it_end)->heuristic;
				//moveMin = (*it_end)->_lastMove;
				//if(beta > max) beta = max;
				//if(beta <= alpha) { max = beta; continue; }
			}
			--it_end;
		}

		if (_currentDepth != _maxDepth && (_currentDepth % 2) == 0)
		{
			this->heuristic = max;
			return (moveMax);
		}
		if (_currentDepth != _maxDepth && (_currentDepth % 2) != 0)
		{
			this->heuristic = min;
			return (moveMin);
		}
	}
	return (Move(-1, -1));
}

void		MyTree::InitPoints()
{
	for (ushort y = 0; y < board->Height; y++)
	{
		for (ushort x = 0; x < board->Width; x++)
		{
			if (GET_COLOR(this->board->Cases[y][x]) != COLOR_NONE)
			{
				BoardCase surrounded = (Board::CheckIfSurrounded(this->board->Cases[y][x]) == true) ? IS_SURROUNDED : 0;
				if (surrounded != 0)
					continue ;
				this->_Points.push_back(Move(x, y));
			}
		}
	}
}

void		MyTree::AddChild(unsigned short x, unsigned short y)
{
	if (x >= 0 && y >= 0 && x < board->Width && y < board->Height && GET_COLOR(board->Cases[y][x]) == COLOR_NONE)
	{
		Arbiter& arbiter = Gomoku::Instance().Arbiter;
		BoardCase color = ((this->_currentDepth % 2) != 0) ? COLOR_WHITE : COLOR_BLACK;
		if (arbiter.CanIMove(x, y, color, *(this->board)) == true)
		{
			if (MyTree::Backup._x == (ushort)-1 && MyTree::Backup._y == (ushort)-1)
				MyTree::Backup = Move(x, y);
			MyTree *t = new MyTree(this->board, x, y, this->_currentDepth);
			_Children.push_back(t);
		}
	}
}

void		MyTree::SetValue(unsigned short x, unsigned short y)
{
	if (x >= 0 && y >= 0 && x < board->Width && y < board->Height && GET_COLOR(this->board->Cases[y][x]) == COLOR_NONE)
	{
		Heuristic h;
		Move m(x, y);

		char c = ((this->_currentDepth % 2) != 0) ? COLOR_WHITE : COLOR_BLACK;
		Board::CreateNewBoardCase(this->board->Cases[y][x], c, x, y, GET_ALIGN_ENMY(this->board->Cases[y][x]), GET_ALIGN_ALLY(this->board->Cases[y][x]), 0);
		BoardCase surounded = (Board::CheckIfSurrounded(this->board->Cases[y][x]) == true) ? IS_SURROUNDED : 0;
		this->board->Cases[y][x] += surounded;
		this->board->UpdateCaseState(this->board->Cases[y][x]);
		this->_Points.push_back(m);
		if (_Children.size() == 0)
			this->heuristic = h.GetMoveValue(this->board, m, GET_COLOR(c));
	}
}

void		MyTree::SetValue(int c, unsigned short x, unsigned short y)
{
	if (x >= 0 && y >= 0 && x < board->Width && y < board->Height && GET_COLOR(board->Cases[y][x]) == COLOR_NONE)
	{
		Board::CreateNewBoardCase(this->board->Cases[y][x], c, x, y, GET_ALIGN_ENMY(this->board->Cases[y][x]), GET_ALIGN_ALLY(this->board->Cases[y][x]), 0);
		BoardCase surounded = (Board::CheckIfSurrounded(this->board->Cases[y][x]) == true) ? IS_SURROUNDED : 0;
		this->board->Cases[y][x] += surounded;
		this->board->UpdateCaseState(this->board->Cases[y][x]);
		this->_Points.push_back(Move(x, y));
	}
}





